const fs = require('fs')
const path = require('path')
const data_link = require('../data/data_link.json')

String.prototype.toObject = function () {
    let val = this.replace(/\s+|"/g, "")
    // if (!this) return this
    let arr = val.split(',')
    let obj = {}
    for (const item of arr) {
        let objItem = item.split('=')
        if (objItem.length != 2) continue
        obj[objItem[0]] = objItem[1]
    }
    return obj
}

var dialogue = []
function AkPlot(page_name) {
    dialogue = []
    this.page_name = page_name
    this.dialogue = dialogue
    this.init = init
}

var data_pic_back = {
    '30_i01': './resource/30_i01.png',
    'bg_black': './resource/bg_black.png'
}
var data_pic_char = {
    'char_401_elysm_na_1#9$1': './resource/char_401_elysm_na_1#9$1.png'
};
var data_audio = {};
var data_override = { title: {}, char: {}, image: {}, tween: {}, override: {} };
var dec_log = { mode: false, element: undefined, options: [], stacks: [] };
var system = {
    // "debug": document.URL.includes("&debug=true"),
    "debug": true,
    "error": { "type": "", "info": undefined, "stat": false },
    "txt": { "max": 0, "index": 0, "now": "", "now_temp": "", "now_index": 0, "dynamic": undefined, "interval": 30, "delay_per": 100, "delay_all": 1200 },
    "flag": { "auto": 0, "respond": 0, "skip": 0 },
    "stats": { "reset": false, "click": false, "theater": false, "auto": false, "multi": false, "log_all": true, "step": false },
    "decision": { "mode": false, "select": 1, "values": [-1, -1, -1] }
};

const txt_page_name = 'IC-1 沉浸式游览/BEG'
const data_nickname = '博士'


function fun_msg(msg_type, msg_debug, ...msgs) {
    if (msg_debug && !system.debug) return;
    let t = new Date();
    let t_txt = t.getFullYear() + "-" + (t.getMonth() + 1) + "-" + t.getDate() + " " + t.getHours() + ":" + t.getMinutes() + ":" + t.getSeconds();
    let data = msgs.slice(1);
    data.unshift(t_txt);
    switch (msg_type) {
        case -2:
            data.unshift("[%s][Error]:" + msgs[0]);
            // console.error(...data);
            break;
        case -1:
            data.unshift("[%s][Warn]:" + msgs[0]);
            // console.warn(...data);
            break;
        case 0:
            data.unshift("[%s][Info]:" + msgs[0]);
            // console.log(...data);
            break;
        case 1:
            data.unshift("%c[%s][Debug]:" + msgs[0], "background-color:orange;");
            // console.log(...data);
            break;
        case 2:
            data.unshift("%c[%s][Info]:" + msgs[0], "color:#0080ff");
            // console.log(...data);
            break;
        case 3:
            data.unshift("%c[%s][Info]:" + msgs[0], "color:#0080ff");
            // console.log(...data);
            break;
    }
}

function fun_override_check(sub, key, line) {
    let ret = false;
    line++;
    switch (sub) {
        case 'char':
            if (data_override.char[key] != undefined && data_override.char[key][line] != undefined) ret = true;
            break;
        case 'image':
            if (data_override.image[key] != undefined && data_override.image[key][line] != undefined) ret = true;
            break;
        case 'override':
            if (data_override.override[key] != undefined && data_override.override[key][line] != undefined) ret = true;
            break;
        case 'tween':
            if (data_override.tween[key] != undefined && data_override.tween[key][line] != undefined) ret = true;
            break;
    }
    return ret;
}

// 人物立绘相关，key_data为立绘名，如：char_401_elysm_na_1#9$1，返回一组坐标:[立绘基础名, 表情查分下标]
function fun_char_link(key_data) {
    let n, i;
    if (key_data.trim() == "" || key_data == undefined) {
        fun_msg(-2, false, "The input parameter is empty,has skipped the data.");
        return [-1, -1];
    }
    let m = key_data.match(/^([^@#$]+)(?:([@#$])([a-z\d]+)|#(\d+)\$(\d+))?$/);
    fun_msg(0, true, "regex match:", m);
    if (m == null) {
        fun_msg(-2, false, "Can't get key from the input parameter,has skipped the data.");
        return [-1, -1];
    }
    // console.log('立绘相关')
    // console.log(m)
    n = m[1], i = m[3];
    if (data_link[n] == undefined) {
        fun_msg(-2, false, "The appointed key [" + n + "] not exist,has skipped the data.");
        return [-1, -1];
    }
    if (m[2] == '$' || (m[4] && m[5])) {
        let g = '$' + (m[5] || i);//group
        i = m[4] || i;
        let ps = data_link[n].array.findIndex((v) => v.name.endsWith(g)), pe = data_link[n].array.findIndex((v, vi) => !v.name.endsWith(g) && vi > ps);
        if (ps == -1) {
            fun_msg(-1, false, "The analyze key [" + n + ":" + i + "] not exist,use the default char to instead.");
            return [n, 0];
        }
        pe = pe == -1 ? data_link[n].array.length - 1 : pe - 1;
        if (m[2]) return [n, ps];
        try {
            i--;
        }
        catch (err) {
            fun_msg(-1, false, "Data analyze error,use the default char to instead.");
            i = ps;
        }
        if (i > pe - ps) {
            fun_msg(-1, false, "The analyze key [" + n + ":" + i + "] is out of range,use the default char to instead.");
            i = ps;
        }
        return [n, i + ps];
    }
    else if (m[2] == "#") {
        try {
            i--;
        }
        catch (err) {
            fun_msg(-1, false, "Data analyze error,use the default char to instead.");
            i = 0;
        }
        if (i >= data_link[n].array.length) {
            fun_msg(-1, false, "The analyze key [" + n + ":" + i + "] is out of range,use the default char to instead.");
            i = 0;
        }
        return [n, i];
    }
    else if (m[2] == '@') {
        for (let idx = 0; idx < data_link[n].array.length; idx++) if (data_link[n].array[idx].alias == i) return [n, idx];
        fun_msg(-1, false, "Data analyze error,use the default char to instead.");
        return [n, 0];
    }
    return [n, 0];
}

// 大概是表情差分管理，key为立绘基础名，idx为下标
function fun_char_format(key, idx) {
    if (data_link[key] == undefined) {
        fun_msg(-2, false, "Character key [" + key + "] not exist,please check the link list.");
        return key;
    }
    return data_link[key].array[idx].name;
}

// 语音音乐相关
function fun_get_audio_url(key) {
    if (!key) return "";
    let p = key.toLowerCase();
    return key.startsWith("$") ? data_audio[p.substr(1)] : key.startsWith("@") ? source_url + p.substr(1) : source_url + p.replace("sound_beta_2", "music") + ".mp3";
}

// 剧情对话相关
function fun_txt_format(key_txt) {
    let t = key_txt.trim().replace(/{@nickname}/ig, data_nickname);
    try {
        t = t.replaceAll("<color=", "<font color=").replaceAll("</color>", "</font>");
        t = t.replaceAll("{@s}", "").replaceAll("\\n", "<br/>");
    }
    catch (err) {
        fun_msg(-1, false, "This browser not support replaceAll function.");
        t = t.replace(/<color=/ig, "<font color=").replace(/<\/color>/ig, "</font>");
        t = t.replace(/{@s}/ig, "")
        t = t.replace(/\\n/g, "<br/>");
    }
    // console.log('剧情对话：')
    // console.log(t)
    return t;
}

// 剧情对话相关，tar为标识，para为人物，名字txt为对话内容
function fun_playback(tar, para, txt = system.txt.now) {
    let name = typeof para === "object" ? para.name : para;
    if (name == undefined) return;
    console.log(txt)
    dialogue.push({
        name,
        dialog: txt
    })
    // let o = document.createElement("li");
    // let n = typeof para === "object" ? para.name : para;
    // if (n == undefined) return;
    // switch (tar) {
    //     case 'playback':
    //     case '@p':
    //         tar = "playback_result";
    //         break;
    //     case 'playback_all':
    //     case '@pa':
    //         tar = dec_log.mode ? dec_log.element : "playback_all_result";
    //         break;
    // }
    // let hei = fun_cal_len(txt, fun_get_font(14), ((tar == "playback_all_result" && dec_log.mode) || system.decision.mode) ? log_limit_px - 14 : log_limit_px) * 22;
    // if (hei > 22) o.style.height = hei + "px";
    // o.innerHTML = (n.trim() == "" ? "" : "<em>" + n + "</em>") + "<span>" + txt + "</span>";
    // if (fun_cal_len(n, fun_get_font(16)) > log_em_limit_px) o.childNodes[0].style.fontSize = "12px";
    // if (typeof para === "object" && para.color != undefined) o.childNodes[0].style.color = para.color;
    // if (typeof tar === "string") tar = document.getElementById(tar);
    // tar.append(o);
}

AkPlot.prototype = {
    
}

async function init() {
    // 计算需要读取的剧情文件名
    
    async function getFiles() {
        return new Promise(res => {
            fs.readdir('../ArknightsGameData/zh_CN/gamedata/story/activities/act25side', (err, files) => {
                res(files)
            })
        })
    }
    let files = await getFiles()
    // console.log(files)
    let fileName = ''
    if (this.page_name && parseInt(this.page_name) && parseInt(this.page_name) < files.length) 
        fileName = files[parseInt(this.page_name)-1]
    else throw ''
    console.log(fileName)
    return new Promise(res => {
        fs.readFile(`../ArknightsGameData/zh_CN/gamedata/story/activities/act25side/${fileName}`, (err, data) => {
            if (err) throw err
            let data_temp = data.toString()
            // console.log(data_temp)
            let data_txt = ''
            if (data_temp) {
                // 不知道为什么在有些篇章的剧情里不一样
                data_txt = data_temp.split("\n")
                // data_txt = data_temp.split("\r\n")
            }
            // console.log(data_txt)
            var data_need = new Set();
            data_temp = "";
            try {
                for (let i = 0; i < data_txt.length; i++) {
                    // 判断是否存在次剧本，txt_page_name为剧本名，如IC-1 沉浸式游览/BEG
                    if (fun_override_check('override', txt_page_name, i)) data_txt[i] = data_override.override[txt_page_name][i + 1];
                    if (data_txt[i] == "" || data_txt[i].match("^\\s+$") || data_txt[i].match("^\\s*//.*$")) continue;
                    let match = data_txt[i].match("^\\[\\s*(?:(.*?)\\((.*)\\)|(?:([\\.|\\w]*)|(.*)))\\s*\\]\\s*(.*)");
                    // console.log(match)
                    let temp = {};
                    if (match == null) {
                        if (system.stats.multi) {
                            fun_playback("@pa", data_temp, system.txt.now);
                            data_temp = "";
                            system.txt.now = "";
                            system.stats.multi = false;
                        }
                        temp.d1 = fun_txt_format(data_txt[i]);
                        fun_playback("@pa", "", temp.d1);
                        continue;
                    };
                    // fun_msg(1, true, "<Debug>Ready to analyze Line [" + i + "]");
                    if (match[1] != undefined) {
                        let cmd_set = match[2].toObject();
                        switch (match[1].toLowerCase()) {
                            case 'background':
                                // temp.n = cmd_set.image ? "bg_" + cmd_set.image.toLowerCase() : "";
                                temp.n = cmd_set.image ? cmd_set.image.toLowerCase() : "";
                                if (temp.n == "") continue;
                                else if (data_pic_back[temp.n] == undefined || data_pic_back[temp.n] == "") {
                                    fun_msg(-2, false, "<Background>Data [" + temp.n + "] not exist,please check the data list.");
                                    continue;
                                }
                                data_need.add(data_pic_back[temp.n]);
                                break;
                            case 'character':
                                temp.n1 = cmd_set.name ? cmd_set.name.toLowerCase() : "";
                                temp.n2 = cmd_set.name2 ? cmd_set.name2.toLowerCase() : "";
                                if (fun_override_check('char', txt_page_name, i)) {
                                    temp.n1 = data_override.char[txt_page_name][i + 1].name || temp.n1;
                                    temp.n2 = data_override.char[txt_page_name][i + 1].name2 || temp.n2;
                                }
                                if (temp.n1 != "") {
                                    [temp.d1, temp.c1] = fun_char_link(temp.n1);
                                    if (temp.d1 == -1) continue;
                                    temp.n1 = fun_char_format(temp.d1, temp.c1);
                                    if (data_pic_char[temp.n1] == undefined || data_pic_char[temp.n1] == "") {
                                        fun_msg(-2, false, "<Character>Data [" + temp.n1 + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_char[temp.n1]);
                                }
                                if (temp.n2 != "") {
                                    [temp.d2, temp.c2] = fun_char_link(temp.n2);
                                    if (temp.d2 == -1) continue;
                                    temp.n2 = fun_char_format(temp.d2, temp.c2);
                                    if (data_pic_char[temp.n2] == undefined || data_pic_char[temp.n2] == "") {
                                        fun_msg(-2, false, "<Character>Data [" + temp.n2 + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_char[temp.n2]);
                                }
                                break;
                            case 'charactercutin':
                                temp.n = cmd_set.name ? cmd_set.name.toLowerCase() : "";
                                if (temp.n != "") {
                                    [temp.d1, temp.c1] = fun_char_link(temp.n)
                                    if (temp.d1 == -1) continue;
                                    temp.n = fun_char_format(temp.d1, temp.c1);
                                    if (data_pic_char[temp.n] == undefined || data_pic_char[temp.n] == "") {
                                        fun_msg(-2, false, "<Charactercutin>Data [" + temp.n + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_char[temp.n]);
                                }
                                break;
                            // 博士选择
                            case 'decision':
                                temp.d1 = cmd_set.options == undefined ? "" : fun_txt_format(cmd_set.options).replace(/;/g, '\n')

                                fun_playback("@pa", '博士の选择：\n', temp.d1);
                                // temp.d1 = cmd_set.options == undefined ? "" : fun_txt_format(cmd_set.options).split(';');
                                // temp.d2 = cmd_set.values == undefined ? "" : cmd_set.values.split(';');
                                // if (temp.d1 == "") continue;
                                // temp.o1 = document.createElement('div');
                                // temp.o1.className = 'log_decision';
                                // temp.o2 = document.createElement("li");
                                // temp.d3 = "";
                                // for (let i of temp.d1) {
                                //     temp.d3 += "<span class='log_decision'>【" + i + "】</span>";
                                // }
                                // temp.o2.innerHTML = temp.d3;
                                // temp.o2.style = "height:" + (temp.d1.length * 22) + "px";
                                // temp.o1.append(temp.o2);
                                // for (let i = 0; i < temp.d1.length; i++) dec_log.options[temp.d2[i]] = temp.d1[i];
                                // if (dec_log.stacks.length > 0 && dec_log.options.length - 1 == dec_log.stacks[dec_log.stacks.length - 1].values.length) {
                                //     dec_log.stacks.pop()
                                //     if (dec_log.stacks.length == 0) {
                                //         dec_log.mode = false;
                                //         document.getElementById("playback_all_result").append(data_temp);
                                //         data_temp = "";
                                //     }
                                // }
                                // if (!dec_log.mode) {
                                //     data_temp = temp.o1;
                                //     dec_log.element = temp.o1;
                                //     dec_log.mode = true;
                                // }
                                // else {
                                //     dec_log.element.append(temp.o1);
                                //     dec_log.element = temp.o2;
                                // }
                                // dec_log.stacks.push({ values: temp.d2, selected: [] });
                                break;
                            case 'image':
                                temp.n = cmd_set.image ? cmd_set.image.toLowerCase() : "";
                                if (temp.n != "") {
                                    if (data_pic_back[temp.n] == undefined || data_pic_back[temp.n] == "") {
                                        fun_msg(-2, false, "<Image>Data [" + temp.n + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_back[temp.n]);
                                }
                                break;
                            case 'largebg':
                                temp.ig = cmd_set.imagegroup ? cmd_set.imagegroup.split("/") : [];
                                for (let i = 0; i < temp.ig.length; i++) {
                                    let n = "bg_" + temp.ig[i].toLowerCase();
                                    if (data_pic_back[n] == undefined || data_pic_back[n] == "") {
                                        fun_msg(-2, false, "<LargeBg>Data [" + n + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_back[n]);
                                }
                                break;
                            case 'largeimg':
                                temp.ig = cmd_set.imagegroup ? cmd_set.imagegroup.split("/") : [];
                                for (let i = 0; i < temp.ig.length; i++) {
                                    let n = temp.ig[i].toLowerCase();
                                    if (data_pic_back[n] == undefined || data_pic_back[n] == "") {
                                        fun_msg(-2, false, "<LargeBg>Data [" + n + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_pic_back[n]);
                                }
                                break;
                            case 'multiline':
                                if (cmd_set.name == undefined) continue;
                                data_temp = cmd_set.name;
                                system.txt.now += fun_txt_format(match[5]);
                                system.stats.multi = true;
                                break;
                            case 'playmusic':
                                temp.d1 = cmd_set.intro == undefined ? "" : cmd_set.intro.replace('$', "").toLowerCase();
                                temp.d2 = cmd_set.key == undefined ? "" : cmd_set.key.replace('$', "").toLowerCase();
                                if (temp.d1 != "") {
                                    if (data_audio[temp.d1] == undefined || data_audio[temp.d1] == "") {
                                        fun_msg(-2, false, "<PlayMusic>Data [" + temp.d1 + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_audio[temp.d1]);
                                }
                                if (temp.d2 != "") {
                                    if (data_audio[temp.d2] == undefined || data_audio[temp.d2] == "") {
                                        fun_msg(-2, false, "<PlayMusic>Data [" + temp.d2 + "] not exist,please check the data list.");
                                        continue;
                                    }
                                    data_need.add(data_audio[temp.d2]);
                                }
                                break;
                            case 'playsound':
                                temp.d1 = fun_get_audio_url(cmd_set.key) || "";
                                if (temp.d1 == "") continue;
                                data_need.add(data_audio[temp.d1]);
                                break;
                            case 'predicate':
                                temp.refs = cmd_set.references == undefined ? [] : cmd_set.references.split(';');
                                if (dec_log.stacks.length == 0) {
                                    fun_msg(-1, false, "<Predicate>The stacks is empty.Has skipped the command.");
                                    continue;
                                }
                                let last_stack = dec_log.stacks.getLast();
                                temp.vlen = last_stack.values.length;
                                temp.refv = temp.refs.filter((x) => last_stack.values.includes(x));
                                temp.otherv = temp.refs.filter((x) => dec_log.options[x] != undefined && !last_stack.values.includes(x));
                                temp.refs = temp.refs.filter((x) => !last_stack.selected.includes(x));
                                if (temp.refv.length == temp.vlen || temp.refs.length == 0) {
                                    dec_log.stacks.pop();
                                    dec_log.element = dec_log.element.parentElement;
                                }
                                if (dec_log.stacks.length == 0 || temp.otherv.length > 0) {
                                    dec_log.mode = false;
                                    dec_log.options = [];
                                    // document.getElementById('playback_all_result').append(data_temp);
                                    data_temp = "";
                                    continue;
                                }
                                if (temp.refs.length > 0) {
                                    // temp.o1 = document.createElement('div');
                                    temp.o1.className = 'log_predicate';
                                    dec_log.element.parentElement == undefined ? dec_log.element.append(temp.o1) : dec_log.element.parentElement.append(temp.o1);
                                    dec_log.element = temp.o1;
                                    for (let i of temp.refs) {
                                        if (dec_log.options[i] == undefined) {
                                            fun_msg(-1, false, "<Predicate>Can't find the options data of the value [" + i + "].");
                                            continue;
                                        }
                                        // temp.o2 = document.createElement('span');
                                        // temp.o2.innerHTML = "【" + dec_log.options[i] + "】";
                                        if (!dec_log.stacks.getLast().selected.includes(i)) dec_log.stacks.getLast().selected.push(i);
                                        dec_log.element.append(temp.o2);
                                    }
                                }
                                break;
                            case 'showitem':
                                temp.d1 = cmd_set.image == undefined ? "" : cmd_set.image.toLowerCase();
                                if (temp.d1 == "") continue;
                                else if (data_pic_back[temp.d1] == undefined || data_pic_back[temp.d1] == "") {
                                    fun_msg(-2, false, "<ShowItem>Data [" + temp.d1 + "] not exist,please check the data list.");
                                    continue;
                                }
                                data_need.add(data_pic_back[temp.d1]);
                                break;
                            case 'sticker':
                            case 'subtitle':
                                temp.d1 = cmd_set.text == undefined ? "" : fun_txt_format(cmd_set.text);
                                if (temp.d1 == "") continue;
                                fun_playback("@pa", "", temp.d1);
                                break;
                            case 'video':
                                temp.d1 = cmd_set.res == undefined ? "" : cmd_set.res.toLowerCase();
                                if (temp.d1 == "") continue;
                                temp.d1 = source_url + temp.d1;
                                data_need.add(temp.d1);
                                break;
                            default:
                                break;
                        }
                        continue;
                    }
                    else if (match[3]) {
                        switch (match[3].toLowerCase()) {
                            case 'predicate':
                                dec_log = { mode: false, options: [], stacks: [] };
                                // document.getElementById('playback_all_result').append(data_temp);
                                data_temp = "";
                                break;
                        }
                        continue;
                    }
                    else if (match[4] && match[5]) {
                        temp.p = match[4].toObject();
                        if (temp.p == null || temp.p.name == undefined) continue;
                        if (system.stats.multi) {
                            fun_playback("@pa", data_temp, system.txt.now);
                            data_temp = "";
                            system.txt.now = "";
                            system.stats.multi = false;
                        }
                        temp.d1 = fun_txt_format(match[5]);
                        fun_playback("@pa", temp.p, temp.d1);
                    }
                }
            }
            catch (err) {
                console.log(err)
                system.error.type = "preload_error";
                system.error.info = err;
                system.error.stat = true;
            }
            finally {
                system.stats.multi = false;//临时使用完毕
                // if (data_temp) {
                //     document.getElementById('playback_all_result').append(data_temp);
                // }
                // data_temp = "";
                // console.log(dialogue)
                // console.log(dialogue)
                res(dialogue) 
            }
        })
    }) 
}

module.exports = AkPlot